#pragma semicolon 1 // Force strict semicolon mode.

#include <sourcemod>
#include <sdktools>
#include <tf2_stocks>
#include <tfx>
#include <psycore>

#define PLUGIN_NAME              "psyFX - Visuals"
#define PLUGIN_AUTHOR            "Thrawn"
#define PLUGIN_VERSION           "1.0.0.0"
#define PLUGIN_CONTACT           "http://aaa.einfachonline.net/"


#define SOUND_CONE 				"ambient/thunder4.wav"
#define SOUND_CURRY 			"vo/pyro_laughevil01.wav"
#define SOUND_HOTHEAD 			"misc/flame_engulf.wav"
#define SOUND_INKPOT 			"weapons/jar_explode.wav"
#define SOUND_INVISIBLE 		"player/spy_cloak.wav"
#define SOUND_INVISIBLE_END 	"player/spy_uncloak.wav"
#define SOUND_STRANGE 			"ambient/cow1.wav"
#define SOUND_NOSTALGIA			"ui/tv_tune.wav"
#define SOUND_AQUA				"ui/tv_tune.wav"

#define MODEL_CONE "models/props_gameplay/orange_cone001.mdl"

#define PLAYER_ONFIRE   (1 << 17)	

new g_iEffectNum[9] = {-1,...};
new Handle:g_clientEffectTimer[MAXPLAYERS + 1];

public Plugin:myinfo = {
    name        = PLUGIN_NAME,
    author      = PLUGIN_AUTHOR,
    description = PLUGIN_NAME,
    version     = PLUGIN_VERSION,
    url         = PLUGIN_CONTACT
};

public OnMapStart()
{
	PrecacheModel(MODEL_CONE, true);

	PrecacheSound(SOUND_CURRY, true);
	PrecacheSound(SOUND_HOTHEAD, true);
	PrecacheSound(SOUND_INVISIBLE, true);
	PrecacheSound(SOUND_INVISIBLE_END, true);
	PrecacheSound(SOUND_STRANGE, true);
	PrecacheSound(SOUND_INKPOT, true);
	PrecacheSound(SOUND_CONE, true);
	PrecacheSound(SOUND_NOSTALGIA, true);
	
}

public OnAllPluginsLoaded() {
	if(LibraryExists("psycore")) {
		g_iEffectNum[0] = psyRTD_RegisterEffect(psyRTDEffectType_Bad,"Feeling Strange","You feel a little strange...", EffectFeelingStrange);
		g_iEffectNum[1] = psyRTD_RegisterEffect(psyRTDEffectType_Bad,"Superspicy Curry","Share this hot dish with the enemy!", EffectSuperspicyCurry);
		g_iEffectNum[2] = psyRTD_RegisterEffect(psyRTDEffectType_Good,"Invisibility Paint","New from ACME Corporation", EffectInvisible);
		g_iEffectNum[3] = psyRTD_RegisterEffect(psyRTDEffectType_Good,"Ink Pot","Instant camoflage!", EffectInkPot);
		g_iEffectNum[4] = psyRTD_RegisterEffect(psyRTDEffectType_Bad,"Hot Head","Your head spontaneously combusted", EffectHotHead);
		g_iEffectNum[5] = psyRTD_RegisterEffect(psyRTDEffectType_Bad,"Traffic Cone","You now have a traffic cone on your head for some reason", EffectCone);
		g_iEffectNum[6] = psyRTD_RegisterEffect(psyRTDEffectType_Bad,"Nostalgia","You feel like you're back in the good ol' days", EffectNostalgia);
		g_iEffectNum[7] = psyRTD_RegisterEffect(psyRTDEffectType_Bad,"Binocular","So near and yet so far...", EffectBinocular);
		g_iEffectNum[8] = psyRTD_RegisterEffect(psyRTDEffectType_Bad,"Aqua","blub blub blub", EffectUnderWater);
	}		
}


public psyRTD_DisableEffect(client,effectId) {
	for(new i = 0; i < sizeof(g_iEffectNum); i++) {
		if(effectId == g_iEffectNum[i]) {
			if(g_clientEffectTimer[client] != INVALID_HANDLE)
				TriggerTimer(g_clientEffectTimer[client]);
		}
	}
}

/* EffectNostalgia()
**
** Effect: Boom.
** ------------------------------------------------------------------------- */
public psyRTDAction:EffectNostalgia(client)
{
	g_clientEffectTimer[client] = CreateTimer(20.0, Timer_Nostalgia, client);
	
	ShowOverlay(client, "debug/yuv", 20.0);	
	EmitSoundClient(SOUND_NOSTALGIA, client);
	
	return psyRTD_Continue;
}

/* Timer_Nostalgia()
**
** Timer for Nostalgia effect.
** ------------------------------------------------------------------------- */
public Action:Timer_Nostalgia(Handle:timer, any:client)
{
	g_clientEffectTimer[client] = INVALID_HANDLE;	
	
	if (client && IsClientInGame(client) && !IsClientInKickQueue(client)) {
		psyRTD_EffectIsNowDisabled(client, g_iEffectNum[6]);
	}
}

/* EffectUnderWater()
**
** Effect: Boom.
** ------------------------------------------------------------------------- */
public psyRTDAction:EffectUnderWater(client)
{
	g_clientEffectTimer[client] = CreateTimer(20.0, Timer_Underwater, client);
	
	ShowOverlay(client, "effects/water_warp_well", 20.0);	
	EmitSoundClient(SOUND_AQUA, client);
	
	return psyRTD_Continue;
}

/* Timer_Nostalgia()
**
** Timer for Nostalgia effect.
** ------------------------------------------------------------------------- */
public Action:Timer_Underwater(Handle:timer, any:client)
{
	g_clientEffectTimer[client] = INVALID_HANDLE;	
	
	if (client && IsClientInGame(client) && !IsClientInKickQueue(client)) {
		psyRTD_EffectIsNowDisabled(client, g_iEffectNum[8]);
	}
}


/* EffectCone()
**
** Effect: Traffic Cone.
** ------------------------------------------------------------------------- */
public psyRTDAction:EffectCone(client)
{
	new Handle:pack, Float:dpos[3], Float:dang[3],
					  Float:pos[3], Float:ang[3];
		
	g_clientEffectTimer[client] = CreateDataTimer(20.0, Timer_Cone, pack);
	
	GetClientAbsAngles(client, ang);
	GetClientAbsOrigin(client, pos);
	
	dpos[0] = pos[0] + Sine(DegToRad(ang[1]));
	dpos[1] = pos[1] + Cosine(DegToRad(ang[1]));
	dpos[2] = pos[2] - 8.0;
	
	dang[0] = 0.0;
	dang[1] = 0.0;
	dang[2] = 0.0;
	
	new cone = CreateEntityByName("prop_dynamic_override");
	
	if (IsValidEntity(cone)) {
		TeleportEntity(cone, dpos, dang, NULL_VECTOR);
		
		SetVariantString("!activator");
		AcceptEntityInput(cone, "SetParent", client, cone, false);
		
		SetVariantString("partyhat");
		AcceptEntityInput(cone, "SetParentAttachmentMaintainOffset");
		
		DispatchKeyValue(cone, "model", MODEL_CONE);
		DispatchKeyValue(cone, "solid", "0");
		
		DispatchSpawn(cone);
		
		AcceptEntityInput(cone, "TurnOn");
	}
	
	WritePackCell(pack, client);
	WritePackCell(pack, cone);
	
	EmitSoundClient(SOUND_CONE, client);
	
	return psyRTD_Continue;
}

/* Timer_Cone()
**
** Timer for cone effect.
** ------------------------------------------------------------------------- */
public Action:Timer_Cone(Handle:timer, Handle:pack)
{
	new client, cone;
	
	ResetPack(pack);
	client = ReadPackCell(pack);
	cone = ReadPackCell(pack);
	
	g_clientEffectTimer[client] = INVALID_HANDLE;
	
	if (IsValidEntity(cone)) {
		RemoveEdict(cone);
	}
	
	if (client && IsClientInGame(client) && !IsClientInKickQueue(client)) {
		psyRTD_EffectIsNowDisabled(client, g_iEffectNum[5]);
	}
}


public psyRTDAction:EffectBinocular(client)
{
	new Handle:pack;
	
	g_clientEffectTimer[client] = CreateDataTimer(10.0, Timer_Binocular, pack);
	
	// Remember the client's FOV (incase they had a number higher than 75)
	WritePackCell(pack, client);
	WritePackCell(pack, GetEntProp(client, Prop_Send, "m_iFOV"));
	WritePackCell(pack, GetEntProp(client, Prop_Send, "m_iDefaultFOV"));
	
	SetEntProp(client, Prop_Send, "m_iFOV", 20);
	SetEntProp(client, Prop_Send, "m_iDefaultFOV", 20);	
	
	EmitSoundClient(SOUND_STRANGE, client);
	
	return psyRTD_Continue;
}

public Action:Timer_Binocular(Handle:timer, Handle:pack)
{
	new client, fov, dfov;
	
	ResetPack(pack);
	client = ReadPackCell(pack);
	fov    = ReadPackCell(pack);
	dfov   = ReadPackCell(pack);
			
	g_clientEffectTimer[client] = INVALID_HANDLE;
	
	if (client && IsClientInGame(client) && !IsClientInKickQueue(client)) {
		SetEntProp(client, Prop_Send, "m_iFOV", fov);
		SetEntProp(client, Prop_Send, "m_iDefaultFOV", dfov);		

		psyRTD_EffectIsNowDisabled(client, g_iEffectNum[7]);		
	}
}

public psyRTDAction:EffectFeelingStrange(client)
{
	new Handle:pack;
	
	g_clientEffectTimer[client] = CreateDataTimer(10.0, Timer_FeelingStrange, pack);
	
	// Remember the client's FOV (incase they had a number higher than 75)
	WritePackCell(pack, client);
	WritePackCell(pack, GetEntProp(client, Prop_Send, "m_iFOV"));
	WritePackCell(pack, GetEntProp(client, Prop_Send, "m_iDefaultFOV"));
	
	SetEntProp(client, Prop_Send, "m_iFOV", 160);
	SetEntProp(client, Prop_Send, "m_iDefaultFOV", 160);	
	
	EmitSoundClient(SOUND_STRANGE, client);
	
	return psyRTD_Continue;
}

public Action:Timer_FeelingStrange(Handle:timer, Handle:pack)
{
	new client, fov, dfov;
	
	ResetPack(pack);
	client = ReadPackCell(pack);
	fov    = ReadPackCell(pack);
	dfov   = ReadPackCell(pack);
			
	g_clientEffectTimer[client] = INVALID_HANDLE;
	
	if (client && IsClientInGame(client) && !IsClientInKickQueue(client)) {
		SetEntProp(client, Prop_Send, "m_iFOV", fov);
		SetEntProp(client, Prop_Send, "m_iDefaultFOV", dfov);		

		psyRTD_EffectIsNowDisabled(client, g_iEffectNum[0]);		
	}
}


/* EffectSuperspicyCurry()
**
** Effect: You and everyone (on the other team) around you get ignited constantly for 10 seconds.
** ------------------------------------------------------------------------- */
public psyRTDAction:EffectSuperspicyCurry(client)
{
	g_clientEffectTimer[client] = CreateTimer(10.0, Timer_SuperspicyCurry, client);
	
	SetEntityHealth(client, GetClientHealth(client) + 50);
	
	ColorizePlayer(client, RED);
	TF2_IgnitePlayer(client, client);
	
	EmitSoundClient(SOUND_CURRY, client);
	
	return psyRTD_Continue;
}

/* Timer_SuperspicyCurry()
**
** Timer for Superspicy Curry effect.
** ------------------------------------------------------------------------- */
public Action:Timer_SuperspicyCurry(Handle:timer, any:client)
{
	g_clientEffectTimer[client] = INVALID_HANDLE;
		
	if (client && IsClientInGame(client) && !IsClientInKickQueue(client)) {
		ColorizePlayer(client, NORMAL);
		psyRTD_EffectIsNowDisabled(client, g_iEffectNum[1]);	
	}
}

/* EffectInvisible()
**
** Effect: Invisibility for 15 seconds.
** ------------------------------------------------------------------------- */
public psyRTDAction:EffectInvisible(client)
{
	g_clientEffectTimer[client] = CreateTimer(10.0, Timer_Invisible, client);
	
	ColorizePlayer(client, INVISIBLE);
	
	for (new i = 0; i < 5; i++) {
		CreateParticle("electrocuted_gibbed_blue", 2.0, client, ATTACH_NORMAL, GetRandomFloat(0.0, 64.0) - 32.0, GetRandomFloat(0.0, 64.0) - 32.0, GetRandomFloat(0.0, 64.0) - 32.0 + 32.0);
	}
	
	// Remove fire
	SetEntProp(client, Prop_Send, "m_nPlayerCond", GetEntProp(client, Prop_Send, "m_nPlayerCond") & (~PLAYER_ONFIRE));
	
	EmitSoundClient(SOUND_INVISIBLE, client);
	
	return psyRTD_Continue;
}

/* Timer_Invisible()
**
** Timer for Invisible effect.
** ------------------------------------------------------------------------- */
public Action:Timer_Invisible(Handle:timer, any:client)
{
	g_clientEffectTimer[client] = INVALID_HANDLE;
	
	if (client && IsClientInGame(client) && !IsClientInKickQueue(client)) {
		ColorizePlayer(client, NORMAL);
		
		for (new i = 0; i < 5; i++) {
			CreateParticle("electrocuted_gibbed_blue", 2.0, client, ATTACH_NORMAL, GetRandomFloat(0.0, 64.0) - 32.0, GetRandomFloat(0.0, 64.0) - 32.0, GetRandomFloat(0.0, 64.0) - 32.0 + 32.0);
		}
		
		EmitSoundClient(SOUND_INVISIBLE_END, client);
		psyRTD_EffectIsNowDisabled(client, g_iEffectNum[2]);
	}
}

/* EffectInkPot()
**
** Effect: You get covered in ink for 20 seconds.
** ------------------------------------------------------------------------- */
public psyRTDAction:EffectInkPot(client)
{
	g_clientEffectTimer[client] = CreateTimer(20.0, Timer_InkPot, client);
	
	ColorizePlayer(client, BLACK);
	
	// Create a bunch of oil droplet particles
	CreateParticle("lowV_oildroplets", 5.0, client, ATTACH_HEAD);
	CreateParticle("lowV_oildroplets", 5.0, client, ATTACH_HEAD);
	CreateParticle("lowV_oildroplets", 5.0, client, ATTACH_HEAD);
	CreateParticle("lowV_oildroplets", 5.0, client, ATTACH_HEAD);
	
	EmitSoundClient(SOUND_INKPOT, client);
	
	return psyRTD_Continue;
}

/* Timer_InkPot()
**
** Timer for Ink Pot effect.
** ------------------------------------------------------------------------- */
public Action:Timer_InkPot(Handle:timer, any:client)
{
	g_clientEffectTimer[client] = INVALID_HANDLE;
	
	if (client && IsClientInGame(client) && !IsClientInKickQueue(client)) {
		ColorizePlayer(client, NORMAL);
		
		psyRTD_EffectIsNowDisabled(client, g_iEffectNum[3]);
	}
}


/* EffectHotHead()
**
** Effect: Your head spontaneously combusted.
** ------------------------------------------------------------------------- */
public psyRTDAction:EffectHotHead(client)
{
	g_clientEffectTimer[client] = CreateTimer(20.0, Timer_HotHead, client);
	CreateParticle("smoke_blackbillow_skybox", 20.0, client, ATTACH_HEAD);	
	
	EmitSoundClient(SOUND_HOTHEAD, client);
	
	return psyRTD_Continue;
}

/* Timer_HotHead()
**
** Timer for Hot Head effect.
** ------------------------------------------------------------------------- */
public Action:Timer_HotHead(Handle:timer, any:client)
{
	g_clientEffectTimer[client] = INVALID_HANDLE;
	
	// Force the particle to be deleted
	if (client && IsClientInGame(client) && !IsClientInKickQueue(client)) {
		psyRTD_EffectIsNowDisabled(client, g_iEffectNum[4]);
	}
}